package com.touch.core.script;
/**
 * The ByteInterpreter class contains all the necessary static methods for the modification of an arrya of bytes.
 */
/*
 * Copyright (c) 2009, TOD Productions All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
 *	- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
 *	- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *	-Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
 */
public class ByteEncoder 
{
	/**
	 * Creates a 16bit byte array from a 16bit character
	 * @param cChar Character to convert
	 */
	public static final byte[] charToByteArray(char cChar) 
	{
		return new byte[] {
			(byte)((cChar >> 8) & 0xff),
			(byte)((cChar >> 0) & 0xff),
		};
	}
	/**
	 * Creates an 8bit byte array from a boolean
	 * @param bBoolean Boolean to convert
	 */
	public static final byte[] booleanToByteArray(boolean bBoolean) 
	{
		return new byte[]{(byte)(bBoolean ? 0x01 : 0x00)};
	}
	/**
	 * Creates a 32bit byte array from an integer
	 * @param int32 Integer to convert
	 */
	public static final byte[] intToByteArray(int int32) 
	{	
		return new byte[] {
			(byte)((int32 >> 24) & 0xff), 
			(byte)((int32 >> 16) & 0xff), 
			(byte)((int32 >> 8) & 0xff),
			(byte)((int32 >> 0) & 0xff),
		};
	}
	/**
	 * Creates a 32bit byte array from a float
	 * @param fInt32 Float to convert
	 */
	public static final byte[] floatToByteArray(float fInt32)
	{
		return intToByteArray(Float.floatToRawIntBits(fInt32));
	}
	/**
	 * Creates a 64bit byte array from a long
	 * @param int64 Long to convert
	 */
	public static final byte[] longToByteArray(long int64)
	{
		return new byte[] {
			(byte)((int64 >> 56) & 0xff),
			(byte)((int64 >> 48) & 0xff),
			(byte)((int64 >> 40) & 0xff),
			(byte)((int64 >> 32) & 0xff),
			(byte)((int64 >> 24) & 0xff),
			(byte)((int64 >> 16) & 0xff),
			(byte)((int64 >> 8)  & 0xff),
			(byte)((int64 >> 0)  & 0xff)
		};
	}
	/**
	 * Creates a 64bit byte array from a double
	 * @param fInt64 Double to convert
	 */
	public static final byte[] doubleToByteArray(double fInt64)
	{
		return longToByteArray(Double.doubleToRawLongBits(fInt64));
	}
	/**
	 * Creates a byte array from a String
	 * @param sString String to convert
	 */
	public static final byte[] stringToByteArray(String sString) 
	{
		return (sString == null) ? null : sString.getBytes();
	}
	/**
	 * Creates a Char from a byte array
	 * @param byteArray Array of bytes to convert
	 */
	public static final char byteArrayToChar(byte[] byteArray)
	{
		return (char)((0xff & byteArray[0]) << 8 |(0xff & byteArray[1]) << 0);
	}
	/**
	 * Creates a Char array from a byte array
	 * @param byteArray Array of bytes to convert
	 */
	public static final char[] byteArrayToCharArray(byte[] byteArray)
	{
		final int size 			= byteArray.length / 2;
		final char[] charArray 	= new char[size];
		byte[] tmpArray;
		for(int s = 0; s < size; s++)
		{
			tmpArray = getSubByteArray(byteArray, s * 2, (s + 1) * 2);
			charArray[s] = byteArrayToChar(tmpArray);
		}
		return charArray;
	}
	/**
	 * Creates a byte array from a Char array
	 * @param charArray Array of characters to convert
	 */
	public static final byte[] charArrayToByteArray(char[] charArray)
	{
		byte[] byteArray	= new byte[charArray.length * 2];
		byte[] tmpArray;
		for(int s = 0; s < charArray.length; s++)
		{
			tmpArray = charToByteArray(charArray[s]);
			byteArray = appendToByteArray(byteArray, tmpArray, s * 2);
		}
		return byteArray;
	}
	public static final short byteArrayToShort(byte[] byteArray, int offset)
	{
		return
			(short) ((0xff & byteArray[offset])		<< 8 |
					(0xff & byteArray[offset + 1])	<< 0);
	}
	/**
	 * Creates an Integer from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static final int byteArrayToInt(byte[] byteArray, int offset)
	{
		return
			(0xff & byteArray[offset])		<< 24 | 
			(0xff & byteArray[offset + 1]) 	<< 16 | 
			(0xff & byteArray[offset + 2])	<< 8  | 
			(0xff & byteArray[offset + 3]) 	<< 0;
	}
	/**
	 * Creates a float from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static final float byteArrayToFloat(byte[] byteArray, int offset)
	{
		return Float.intBitsToFloat(byteArrayToInt(byteArray, offset));
	}
	/**
	 * Creates a long from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static final int byteArrayToLong(byte[] byteArray, int offset)
	{
		return
			(0xff & byteArray[offset])		<< 56 |
			(0xff & byteArray[offset + 1])	<< 48 |
			(0xff & byteArray[offset + 2])	<< 40 |
			(0xff & byteArray[offset + 3])	<< 32 |
			(0xff & byteArray[offset + 4])  << 24 |
			(0xff & byteArray[offset + 5])  << 16 |
			(0xff & byteArray[offset + 6])	<< 8  |
			(0xff & byteArray[offset + 7])  << 0;
	}
	/**
	 * Creates a double from a byte array
	 * @param byteArray Byte array to convert
	 * @param offset Offset to start parsing
	 */
	public static final double byteArrayToDouble(byte[] byteArray, int offset)
	{
		return Double.longBitsToDouble(byteArrayToLong(byteArray, offset));
	}
	/**
	 * Creates a String from a byte array
	 * @param byteArray Byte array to convert
	 */
	public static final String byteArrayToString(byte[] byteArray) 
	{
		return new String(byteArray);
	}
	/**
	 * Adds a byte array to another byte array
	 * @param dArray Array to append to
	 * @param sArray Array to append
	 * @param offset Offset to start appending
	 */
	public static final byte[] appendToByteArray(byte[] dArray, byte[] sArray, int offset)
	{
		for(int i = 0; i < sArray.length; i++)		
			dArray[offset + i] = sArray[i];		
		return dArray;
	}
	/**
	 * Adds a byte array to the end of a byte array
	 * @param dArray Byte array to append to
	 * @param sArray Byte array to append
	 */
	public static final byte[] appendToByteArray(byte[] dArray, byte[] sArray)
	{
		final int endOfArray = dArray.length;
		dArray = endOfArray < endOfArray + sArray.length ? expandByteArray(dArray, sArray.length) : dArray;		
		for(int i = 0; i < sArray.length; i++)
			dArray[endOfArray + i] = sArray[i];
		return dArray;			
	}
	public static final byte[] appendToByteArray(byte[] dArray, byte[] ... sArray)
	{
		for(byte[] bArray: sArray)
			dArray = appendToByteArray(dArray, bArray);
		return dArray;
	}
	/**
	 * Returns a byte array from another byte array
	 * @param byteArray Byte array to parse
	 * @param offset_START Starting location
	 * @param offset_END Ending location
	 */
	public static final byte[] getSubByteArray(byte[] byteArray, int offset_START, int offset_END)
	{
		final byte[] byteBuffer = new byte[offset_END - offset_START];
		for(int i = offset_START; i < offset_END; i++)		
			byteBuffer[i - offset_START] = byteArray[i];	
		return byteBuffer;
	}
	/**
	 * Extends the maximum size of a byte array
	 * @param byteArray Byte array to expand
	 * @param appendLength Size to extend array
	 * @return
	 */
	public static final byte[] expandByteArray(byte[] byteArray, int appendLength)
	{
		final byte[] cArray = byteArray.clone();		
		byteArray = new byte[cArray.length + appendLength];
		for(int i = 0; i < cArray.length; i++)
			byteArray[i] = cArray[i];
		return byteArray;
	}
	/**
	 * Compares to byte arrays
	 * @param array1 Array 1 
	 * @param array2 Array 2
	 */
	public static final boolean compareByteArray(byte[] array1, byte[] array2)
	{
		return array1.equals(array2);		
	}
	/**
	 * Converts a String to an array of Char
	 * @param sVal String to convert
	 */
	public static final char[] stringToCharArray(String sVal)
	{		
		return sVal.toCharArray();
	}
	/**
	 * Converts an array of Char to a String
	 * @param charArray Array of Chars to convert
	 */
	public static final String charArrayToString(char[] charArray)
	{
		return new String(charArray);
	}
	/**
	 * Converts an Integer to a 4byte String
	 * @param val Integer to convert
	 */
	public static final String appendIntegerToString(int val)
	{
		final byte[] comCode = 	intToByteArray(val);
		final char[] chrCode = 	byteArrayToCharArray(comCode);
		return 				charArrayToString(chrCode);
	}
	/**
	 * Converts a float to a 4byte String
	 * @param val float to convert
	 */
	public static final String appendFloatToString(float val)
	{
		final byte[] comCode = 	floatToByteArray(val);
		final char[] chrCode = 	byteArrayToCharArray(comCode);
		return				charArrayToString(chrCode);
	}	
	/**
	 * Returns an Integer from a String
	 * @param val String to parse
	 * @param offset Offset to start parsing
	 */
	public static final int getIntFromString(String val, int offset)
	{
		final char[] chrCode = new char[2];
		final byte[] comCode;
		
		val.getChars(offset, offset + 2, chrCode, 0);
		comCode = charArrayToByteArray(chrCode);
		return byteArrayToInt(comCode, 0);
	}
	/**
	 * Returns a float from a String
	 * @param val String to parse
	 * @param offset Offset to start parsing
	 */
	public static final float getFloatFromString(String val, int offset)
	{
		final char[] chrCode = new char[2];
		final byte[] comCode;
		
		val.getChars(offset, offset + 2, chrCode, 0);
		comCode = charArrayToByteArray(chrCode);
		return byteArrayToFloat(comCode, 0);
	}
	
}

